package chat

import (
	"encoding/json"
	"errors"
	"time"

	netpack "im/im_server/proto"
	"strconv"

	"github.com/go-redis/redis/v9"
	"google.golang.org/protobuf/proto"
)

// _, err := ch.chatServer.redisClient.Eval(
// 	ctx,
// 	"if redis.call('get', KEYS[1]) == ARGV[1] then redis.call('del', KEYS[1]) end return redis.call('set', KEYS[1], ARGV[2], 'ex', ARGV[3], 'nx')",
// 	[]string{"key"},
// 	"hello",
// ).Result()

type LoginMessageLogic struct {
	chatServer *ChatServer
	redisCmd   *RedisCmd
}

func (l *LoginMessageLogic) CreatePlayerProcess(csLogin *netpack.CSLogin, c *Connection,
	playerId int64) (*netpack.DBPlayer, error) {
	dbPlayerData := &netpack.DBPlayer{
		Age:           csLogin.Age,
		Email:         csLogin.Email,
		PlayerName:    csLogin.PlayerName,
		Account:       csLogin.Account,
		LastLoginTime: time.Now().Unix(),
		PlayerId:      playerId,
	}

	jsonPlayerData, err := json.Marshal(dbPlayerData)
	if err != nil {
		return nil, err
	}

	err = l.redisCmd.HSetNXRedisPlayerValue(ctx,
		ServerID+HashKeyPlayerIdStr+strconv.FormatInt(playerId, 10), ServerID+HashFiledPlayerStr,
		string(jsonPlayerData))
	if err != nil {
		return nil, err
	}
	return dbPlayerData, nil
}

func (l *LoginMessageLogic) RegisterAccountProcess(csLogin *netpack.CSLogin, c *Connection) (*netpack.DBPlayer, error) {
	playerIdIncrby, err := l.redisCmd.GetRedisIncrByValue(ctx, ServerID+IncrbyPlayerIdStr)
	if err != nil {
		return nil, err
	}

	err = l.redisCmd.SetNXRedisAccountValue(ctx, ServerID+StringKeyAccountStr+csLogin.Account, strconv.FormatInt(playerIdIncrby, 10))
	if err != nil {
		return nil, err
	}
	return l.CreatePlayerProcess(csLogin, c, playerIdIncrby)
}

func (l *LoginMessageLogic) Login(msg proto.Message, c *Connection) error {
	csLogin, ok := msg.(*netpack.CSLogin)
	if !ok {
		return errors.New("parse login message error")
	}

	playerId, err := l.redisCmd.GetRedisAccountValue(ctx, ServerID+StringKeyAccountStr+csLogin.Account)
	if err != nil && err != redis.Nil {
		return err
	}

	var dbPlayerData *netpack.DBPlayer = nil
	if err == redis.Nil {
		dbPlayerData, err = l.RegisterAccountProcess(csLogin, c)
		if err != nil {
			return err
		}
	} else {
		dbPlayerData, err = l.redisCmd.HGetRedisPlayerValue(ctx,
			ServerID+HashKeyPlayerIdStr+strconv.FormatInt(playerId, 10), ServerID+HashFiledPlayerStr)
		if err != nil && err == redis.Nil {
			l.CreatePlayerProcess(csLogin, c, playerId)
		} else if err != nil {
			return err
		}
	}

	c.player.PlayerId = dbPlayerData.PlayerId
	l.chatServer.registerPlayer <- c

	// log.Println(csLogin)
	scLogin := &netpack.SCLogin{}
	scLogin.DbPlayerData = dbPlayerData
	scLogin.Error = netpack.ErrCode_SUCCESS
	return c.reply(netpack.MessageID_SC_LOGIN, scLogin)
}
